package logic;

import gui.GuiMain;

import java.util.Calendar;
import java.util.PriorityQueue;

import memory.GenericEvents;
import memory.Memory;

public class Mark{

	private static final int INCOMPLETE_OR_UPCOMING = 0;
	private static final int COMPLETED_OR_OVER = 1;
	private static final int OVERDUE_OR_ONGOING = 2;
	private static final String EVENT = "Event";
	private static final int UPCOMING = 0;
	private static final int OVER = 1;
	private static final int ONGOING = 2;
	private static final String DEADLINE = "Deadline";
	private static final int INCOMPLETE = 0;
	private static final int OVERDUE = 2;
	private static final String TASK = "Task";

	//@author A0096677H
	// Toggles given item's status
	// Updates display and quick view with change
	public static void markDirectly(GenericEvents item) {
		assert item != null;
		markItem(item);
		Display.displayDetailed(item);
		GuiMain.observerList.notifyUIs(item.getType());
	}

	//@author A0096677H
	// Toggles item's status
	// Depending on item type and relative to current time, deadlines could become complete, incomplete or overdue
	// Events could become upcoming, ongoing, and over
	private static void markItem(GenericEvents item) {
		if ((item.getState() == INCOMPLETE_OR_UPCOMING) || (item.getState() == OVERDUE_OR_ONGOING)) {	// If incomplete or overdue or upcoming or ongoing,
			item.setState(COMPLETED_OR_OVER);
		} else if (item.getState()==COMPLETED_OR_OVER) {
			unmark(item);
		}
		refreshMark(GuiMain.mem,0);
	}

	//@author A0096677H
	// Sets item's marked state to unmarked
	private static void unmark(GenericEvents item) {
		if (item.getType().equals(TASK)){
			item.setState(INCOMPLETE);
		} else if (item.getType().equals(DEADLINE)){
			unmarkDeadline(item);
		} else if (item.getType().equals(EVENT)){
			unmarkEvent(item);
		}
	}

	//@author A0096677H
	// Checks current time and sets either ongoing or upcoming status
	private static void unmarkEvent(GenericEvents item) {
		if (item.getStart().before(Calendar.getInstance()) && item.getEnd().after(Calendar.getInstance())){
			item.setState(ONGOING);
		} else {
			item.setState(UPCOMING);
		}
	}

	//@author A0096677H
	// Checks current time and sets either overdue or incomplete status
	private static void unmarkDeadline(GenericEvents item) {
		if (item.getEnd().before(Calendar.getInstance())){
			item.setState(OVERDUE);
		} else {
			item.setState(INCOMPLETE);
		}
	}

	//@author A0096677H
	// Toggles currently viewed item's marked status
	// Updates display and quick view with change
	public static void markItemsInDisplay(){
		assert Display.detailedView != null;

		markItem(Display.detailedView);
		Display.displayDetailed(Display.detailedView);
		GuiMain.observerList.notifyUIs(Display.detailedView.getType());
	}

	//@author A0096677H
	// Toggles currently listed item's marked status according to list of index
	// Updates display and quick view with change
	public static void markItemsInListView(PriorityQueue<Integer> queue){
		while (!queue.isEmpty()) {
			GenericEvents item = Display.listView.get(queue.remove()-1);
			markItem(item);
			GuiMain.observerList.notifyUIs(item.getType());
		}

		Display.refreshDisplay();
		refreshMark(GuiMain.mem,0);
	}

	//@author A0096677H
	// Rechecks all item in memory with current time to reflect changes such as overdue, ongoing and over status
	// Delay is to give allowance for inaccuracies in timer calling this method
	public static void refreshMark(Memory memory, int delay) {
		try {
			Thread.sleep(delay);
		} catch(InterruptedException e) {
			Thread.currentThread().interrupt();
		}

		for (int i=0; i<memory.getSize(); i++){
			GenericEvents item = memory.get(i);
			refreshIncomplete(item);
		}
	}

	//@author A0096677H
	// Checks incomplete deadline or events with current time and update status
	private static void refreshIncomplete(GenericEvents item) {
		if (item.getState()!= COMPLETED_OR_OVER){
			if (item.getType().equals(DEADLINE)){
				unmarkDeadline(item);
			}
			if (item.getType().equals(EVENT)) {
				refreshEvent(item);
			}
		}
	}

	//@author A0096677H
	// Checks events with current time and update status
	private static void refreshEvent(GenericEvents item) {
		if (item.getStart().before(Calendar.getInstance()) && item.getEnd().after(Calendar.getInstance())){
			item.setState(ONGOING);
		} else if (item.getStart().before(Calendar.getInstance()) && item.getEnd().before(Calendar.getInstance())){
			item.setState(OVER);
		} else {
			item.setState(UPCOMING);
		}
	}

}
